#include "awakener.hpp"
#include "event_loop.hpp"
#include "event_trace.hpp"
#include <error.h>

using namespace event_framework;


bool Awakener::Init()
{
    int evtfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (evtfd < 0)
    {
        EVENT_TRACE_ERROR("[Awakener::Init] create eventfd failed with err=" << error);
        return false;
    }
    wakeupChannel = std::make_shared<Channel>(loop, evtfd);
    ASSERT(wakeupChannel != nullptr);
    wakeupChannel->ConcernReadableEvent(std::bind(&Awakener::HandleWakeupEvent, this));
    return true;
}
void Awakener::Wakeup()
{
    // wake up eventfd to immediately execute cmd
    unsigned long long data = 1;
    ASSERT(wakeupChannel->Fd() > 0);
    int num = write(wakeupChannel->Fd(), &data, sizeof data);
    if (num != sizeof data)
    {
        EVENT_TRACE_ERROR("[Awakener::Wakeup] write event fd with err=" << error);
    }
}
void Awakener::HandleWakeupEvent()
{
    unsigned long long data = 1;
    ASSERT(wakeupChannel->Fd() > 0);
    int num = read(wakeupChannel->Fd(), &data, sizeof data);
    if (num != sizeof data)
    {
        EVENT_TRACE_ERROR("[Awakener::HandleWakeupEvent] read event fd with err=" << error);
    }
}